package gui;

import gui.RoundedTextField.RoundedBorder;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.KeyEventDispatcher;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Stack;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class UserCommand extends JPanel {
	private Observer observer;
	private RoundedTextField roundTextField;
	private ImageLabel defaultButton1, defaultButton2, defaultButton3;
	private String[] templates = {
			"add sd <StartDate> st <StartTime> ed <EndDate> et <EndTime> <<Task>>",
			"del <index>",
			"dis <type>",
			"edi <index> sd <StartDate> ed <EndDate> st <startTime> et <EndTime> <<newTask>>",
			"src <keyword>", "done <index>", "undone <index>" ,"undo", "redo", "exit" };
	private JTextField feedBack;
	private Font textFont;
	private static UserCommand onlyOne;
	private Stack<String> upKeyStack;
	private Stack<String> downKeyStack;

	private UserCommand() {
		upKeyStack = new Stack<String>();
		downKeyStack = new Stack<String>();
		
		setPreferredSize(new Dimension(Dimensions._userCommandWidth,
				Dimensions._userCommandHeight));
		observer = Observer.getInstance();
		loadUserCommand();
		// FOR EVENTS DISPATCHER
		KeyboardFocusManager.getCurrentKeyboardFocusManager()
				.addKeyEventDispatcher(new focusOnEnter());
	}

	public static UserCommand getInstance() {
		if (onlyOne == null) {
			onlyOne = new UserCommand();
		}
		return onlyOne;
	}

	public void grabFocus() {
		roundTextField.grabFocus();
		roundTextField.addFocusListener(new FocusListener() {

			@Override
			public void focusGained(FocusEvent arg0) {
				roundTextField.setOpacity(230);
				roundTextField.setForeground(new Color(0, 0, 0));
				roundTextField.setFont(textFont);
				roundTextField.setText("");
			}

			@Override
			public void focusLost(FocusEvent arg0) {
				roundTextField.setOpacity(120);
				roundTextField.setFont(new Font("Comic Sans MS", Font.ITALIC,
						15));
				roundTextField.setForeground(new Color(0, 0, 0, 70));
				roundTextField.setText(" Enter Command Here...");
			}

		});
	}
	
	public void currRowSelection(String message){
		defaultButton1.changeImage(ImagesDirectory.defaultButton);
		defaultButton2.changeImage(ImagesDirectory.defaultButton);
		defaultButton3.changeImage(ImagesDirectory.defaultButton);
		feedBack.setForeground(Color.CYAN);
		feedBack.setText(message);
	}
	
	public void changeImageWhenValid(String message) {
		defaultButton1.changeImage(ImagesDirectory.greenButton);
		defaultButton2.changeImage(ImagesDirectory.defaultButton);
		defaultButton3.changeImage(ImagesDirectory.defaultButton);
		feedBack.setForeground(Color.GREEN);
		feedBack.setText(message);
	}

	public void changeImageWhenInvalid(String message) {
		defaultButton1.changeImage(ImagesDirectory.defaultButton);
		defaultButton2.changeImage(ImagesDirectory.defaultButton);
		defaultButton3.changeImage(ImagesDirectory.redButton);
		feedBack.setForeground(Color.RED);
		feedBack.setText(message);
	}

	private void loadUserCommand() {
		setLayout(new BorderLayout());
		setBorder(BorderFactory.createTitledBorder("TYPE COMMAND HERE"));

		JPanel tempPanel = new JPanel(new FlowLayout());
		roundTextField = new RoundedTextField(
				Dimensions._roundTextFieldDimension);
		roundTextField.setBorder(BorderFactory.createCompoundBorder(
				new RoundedBorder(), roundTextField.getBorder()));
		
		textFont = new Font("Comic Sans MS", 0, 15);
		roundTextField.setFont(textFont);
		tempPanel.add(roundTextField);
		feedBack = new JTextField(Dimensions._feedBackDimension);
		feedBack.setBorder(null);

		initTextField();

		roundTextField.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				String input = roundTextField.getText();
				roundTextField.setText("");
				setInput(input);
				
			}
		});
		roundTextField.addKeyListener(new KeyListener() {

			String temp;
			String[] getCommand;

			public void keyPressed(KeyEvent arg0) {
				upDownKeyDisplay(arg0);	
				if (!(temp = roundTextField.getText()).equals("")) {
					changeImageWhenTyping();
					for (String s : templates) {
						getCommand = s.split(" ");
						if (getCommand[0].startsWith(temp.toLowerCase())) {
							feedBack.setForeground(Color.ORANGE);
							feedBack.setText(s);
						}
					}
				} else {
					for (String s : templates) {
						if (s.contains(feedBack.getText()))
							feedBack.setText("");
					}
					if (feedBack.getText().isEmpty())
						resetToDefaultButton();
				}
				
			}

			public void keyReleased(KeyEvent arg0) {
				//upDownKeyDisplay(arg0);	
				if (!(temp = roundTextField.getText()).equals("")) {
					changeImageWhenTyping();
					for (String s : templates) {
						getCommand = s.split(" ");
						if (getCommand[0].startsWith(temp.toLowerCase())) {
							feedBack.setForeground(Color.ORANGE);
							feedBack.setText(s);
						}
					}
				} else {
					for (String s : templates) {
						if (s.contains(feedBack.getText()))
							feedBack.setText("");
					}
					if (feedBack.getText().isEmpty())
						resetToDefaultButton();
				}

			}

			

			public void keyTyped(KeyEvent arg0) {
			//	upDownKeyDisplay(arg0);			
				if (!(temp = roundTextField.getText()).equals("")) {
					changeImageWhenTyping();
					for (String s : templates) {
						getCommand = s.split(" ");
						if (getCommand[0].startsWith(temp.toLowerCase())) {
							feedBack.setForeground(Color.ORANGE);
							feedBack.setText(s);
						}
					}
				} else {
					for (String s : templates) {
						if (s.contains(feedBack.getText()))
							feedBack.setText("");
					}
					if (feedBack.getText().isEmpty())
						resetToDefaultButton();
				}
			}
		});

		initButtons(tempPanel);

		feedBack.setEditable(false);
		feedBack.setOpaque(true);
		feedBack.setBackground(new Color(153,153,153));
		
		JPanel mainCommand = new JPanel(new FlowLayout());
		mainCommand.add(feedBack);
		mainCommand.setOpaque(false);
		add(tempPanel, BorderLayout.CENTER);
		add(mainCommand, BorderLayout.SOUTH);

		tempPanel.setOpaque(false);
		roundTextField.setOpaque(false);
		setOpaque(false);

	}
	
	private void upDownKeyDisplay(KeyEvent arg0) {
		String item;
		int code = arg0.getKeyCode();
		
		switch(code){
		case KeyEvent.VK_UP:
			if(!upKeyStack.isEmpty()){
				item = upKeyStack.pop();
				roundTextField.setText(item);
				downKeyStack.push(item);	
			}
			break;
		
		case KeyEvent.VK_DOWN:
			if(!downKeyStack.isEmpty()){
				item = downKeyStack.pop();
				roundTextField.setText(item);					
				upKeyStack.push(item);	
			}if(downKeyStack.isEmpty() && !upKeyStack.isEmpty()){
				roundTextField.setText("");
			}
			break;
		}
		
		String temp;
		String[] getCommand;
		if (!(temp = roundTextField.getText()).equals("")) {
			changeImageWhenTyping();
			for (String s : templates) {
				getCommand = s.split(" ");
				if (getCommand[0].startsWith(temp.toLowerCase())) {
					feedBack.setForeground(Color.ORANGE);
					feedBack.setText(s);
				}
			}
		}else {
			for (String s : templates) {
				if (s.contains(feedBack.getText()))
					feedBack.setText("");
			}
			if (feedBack.getText().isEmpty())
				resetToDefaultButton();
		}
		
	}
	private void initTextField() {
		roundTextField.setOpacity(120);
		roundTextField.setFont(new Font("Comic Sans MS", Font.ITALIC, 15));
		roundTextField.setForeground(new Color(0, 0, 0, 70));
		roundTextField.setText(" Enter Command Here...");
	}

	private void initButtons(JPanel tempPanel) {
		defaultButton1 = new ImageLabel(ImagesDirectory.defaultButton);
		defaultButton1.setPreferredSize(new Dimension(12, 12));
		tempPanel.add(defaultButton1);

		defaultButton2 = new ImageLabel(ImagesDirectory.defaultButton);
		defaultButton2.setPreferredSize(new Dimension(12, 12));
		tempPanel.add(defaultButton2);

		defaultButton3 = new ImageLabel(ImagesDirectory.defaultButton);
		defaultButton3.setPreferredSize(new Dimension(12, 12));
		tempPanel.add(defaultButton3);
	}
	
	private void resetToDefaultButton() {
		defaultButton1.changeImage(ImagesDirectory.defaultButton);
		defaultButton2.changeImage(ImagesDirectory.defaultButton);
		defaultButton3.changeImage(ImagesDirectory.defaultButton);
	}

	private void changeImageWhenTyping() {
		defaultButton1.changeImage(ImagesDirectory.defaultButton);
		defaultButton2.changeImage(ImagesDirectory.yellowButton);
		defaultButton3.changeImage(ImagesDirectory.defaultButton);
	}
	
	protected void setInput(String mainInput) {
		observer.passToControl(mainInput);
		upKeyStack.push(mainInput);
		downKeyStack.clear();
	}

	private class focusOnEnter implements KeyEventDispatcher {

		@Override
		public boolean dispatchKeyEvent(KeyEvent arg0) {
			if (arg0.getID() == KeyEvent.KEY_PRESSED)
				if (arg0.getKeyCode() == KeyEvent.VK_ENTER)
					roundTextField.grabFocus();
			return false;
		}

	}
}
